package clientset

import (
	"context"
	"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/rest"
)

//go:generate go run github.com/vektra/mockery/v2@v2.20.2 --name=TriggerInterface
type TriggerInterface interface {
	List(ctx context.Context, opts metav1.ListOptions) (*v1alpha1.TriggerList, error)
	Get(ctx context.Context, name string, options metav1.GetOptions) (*v1alpha1.Trigger, error)
	Update(ctx context.Context, trigger *v1alpha1.Trigger, opts metav1.UpdateOptions) (result *v1alpha1.Trigger, err error)
	UpdateStatus(ctx context.Context, hostEntry *v1alpha1.Trigger, opts metav1.UpdateOptions) (*v1alpha1.Trigger, error)
	Create(ctx context.Context, trigger *v1alpha1.Trigger) (*v1alpha1.Trigger, error)
	Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
	Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
}

type triggerClient struct {
	restClient rest.Interface
	ns         string
}

func (c *triggerClient) List(ctx context.Context, opts metav1.ListOptions) (*v1alpha1.TriggerList, error) {
	result := v1alpha1.TriggerList{}
	err := c.restClient.
		Get().
		Namespace(c.ns).
		Resource("triggers").
		VersionedParams(&opts, scheme.ParameterCodec).
		Do(ctx).
		Into(&result)

	return &result, err
}

func (c *triggerClient) Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1alpha1.Trigger, error) {
	result := v1alpha1.Trigger{}
	err := c.restClient.
		Get().
		Namespace(c.ns).
		Resource("triggers").
		Name(name).
		VersionedParams(&opts, scheme.ParameterCodec).
		Do(ctx).
		Into(&result)

	return &result, err
}

func (c *triggerClient) Update(ctx context.Context, trigger *v1alpha1.Trigger, opts metav1.UpdateOptions) (result *v1alpha1.Trigger, err error) {
	result = &v1alpha1.Trigger{}
	err = c.restClient.Put().
		Namespace(c.ns).
		Resource("triggers").
		Name(trigger.Name).
		VersionedParams(&opts, scheme.ParameterCodec).
		Body(trigger).
		Do(ctx).
		Into(result)
	return
}

func (c *triggerClient) UpdateStatus(ctx context.Context, hostEntry *v1alpha1.Trigger, opts metav1.UpdateOptions) (result *v1alpha1.Trigger, err error) {
	result = &v1alpha1.Trigger{}
	err = c.restClient.Put().
		Namespace(c.ns).
		Resource("triggers").
		Name(hostEntry.Name).
		SubResource("status").
		VersionedParams(&opts, scheme.ParameterCodec).
		Body(hostEntry).
		Do(ctx).
		Into(result)
	return
}

func (c *triggerClient) Create(ctx context.Context, trigger *v1alpha1.Trigger) (*v1alpha1.Trigger, error) {
	result := v1alpha1.Trigger{}
	err := c.restClient.
		Post().
		Namespace(c.ns).
		Resource("triggers").
		Body(trigger).
		Do(ctx).
		Into(&result)

	return &result, err
}

func (c *triggerClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
	return c.restClient.
		Delete().
		Namespace(c.ns).
		Resource("triggers").
		Name(name).
		Body(&opts).
		Do(ctx).
		Error()
}

func (c *triggerClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
	opts.Watch = true
	return c.restClient.
		Get().
		Namespace(c.ns).
		Resource("trigger").
		VersionedParams(&opts, scheme.ParameterCodec).
		Watch(ctx)
}
